package com.atguigu.service;

import com.atguigu.bean.Employee;
import com.atguigu.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.List;

// 抽取缓存的公共部分
@CacheConfig(cacheNames = "emp")
@Service
public class EmployeeService {
    @Autowired
    private EmployeeMapper employeeMapper;

    public List<Employee> getEmps() {
        return employeeMapper.getEmps();
    }

    /**
     * @Cacheable 将方法的运行结果放入缓存
     * 1、在调用方法之前，先去查看是否有缓存
     * 2、有缓存就不调用目标方法，直接读取缓存
     * 3、没有缓存，就调用目标方法
     * 4、将目标方法的返回结果，放入缓存中
     */
    @Cacheable(value = {"emp"}/*, keyGenerator = "myKeyGenerator", condition = "#a0>1", unless = "#result==null"*/)
    public Employee getEmpById(Integer id) {
        System.out.println("getEmpById : " + id);
        return employeeMapper.getEmpById(id);
    }

    public Employee addEmp(Employee emp) {
        employeeMapper.insertEmp(emp);
        return emp;
    }

    /**
     * @CachePut 同步更新缓存
     * 1、先调用目标方法
     * 2、再把目标方法的结果缓存起来(如果没有配置key，方法的参数值就作为key)
     */
    @CachePut(value = "emp", key = "#emp.id")
    public Employee editEmp(Employee emp) {
        System.out.println("editEmp : " + emp);
        employeeMapper.updateEmp(emp);
        return emp;
    }

    /**
     * @CacheEvict 缓存清除
     * 默认是在方法执行之后，移除缓存
     * beforeInvocation=true，在调用之前移除缓存
     * allEntries=true，移除所有缓存
     */
    @CacheEvict(value = "emp", beforeInvocation = true)
    public int deleteEmp(Integer id) {
        System.out.println("deleteEmp : " + id);
        // return 10 / 0;
        return employeeMapper.deleteEmp(id);
    }

    /**
     * @Caching 定义复杂的缓存规则
     */
    @Caching(
            cacheable = {
                    @Cacheable(/*value = "emp", */key = "#name")
            },
            put = {
                    @CachePut(/*value = "emp", */key = "#result.id"),
                    @CachePut(/*value = "emp", */key = "#result.email")
            }
    )
    public Employee getEmpByName(String name) {
        System.out.println("getEmpByName : " + name);
        return employeeMapper.getEmpByName(name);
    }
}
